package com.appointment.pay.rest.controller;

import java.util.Map;
import java.util.SortedMap;
import java.util.TreeMap;

import javax.servlet.http.HttpServletResponse;

import org.apache.commons.lang.StringUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.core.StringRedisTemplate;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;
import org.springframework.web.bind.annotation.ResponseBody;

import com.appointment.pay.rest.service.IWxPayTransactionService;
import com.appointment.pay.rest.util.SignUtils;
import com.appointment.pay.rest.util.XMLUtil;

/**
 * 微信支付异步通知处理
 * @author zhul
 *
 */
@Controller
@RequestMapping("/wxpay")
public class WxpayController {
    
    private static Logger logger = LoggerFactory.getLogger(WxpayController.class);
    
    @Autowired
    private StringRedisTemplate redisTemplate;
    
    @Autowired
    private IWxPayTransactionService iWxPayTransactionService;
    
    @RequestMapping(value="/notify",method=RequestMethod.POST)
    public @ResponseBody String notify(HttpServletResponse response,@RequestBody String bodyStr) {
        String title = "WxpayController 请求 ";
        logger.info(title + " start..........");
        logger.info("微信支付异步通知参数：");
        logger.info("request bodyStr="+ bodyStr);
        try {
            Map resultMap = XMLUtil.doXMLParse(bodyStr);
            if(resultMap == null){
                logger.error("微信支付异步通知参数为空。");
            }
            
            SortedMap<Object,Object> parameters = new TreeMap<Object,Object>();
            String return_code = (String)resultMap.get("return_code");//返回状态码
            String return_msg = (String)resultMap.get("return_msg");//返回信息
            String appid = (String)resultMap.get("appid");
            String mch_id = (String)resultMap.get("mch_id");
            String device_info = (String)resultMap.get("device_info");
            String nonce_str = (String)resultMap.get("nonce_str");
            String sign = (String)resultMap.get("sign");
            String result_code = (String)resultMap.get("result_code");
            String err_code = (String)resultMap.get("err_code");
            String err_code_des = (String)resultMap.get("err_code_des");
            String openid = (String)resultMap.get("openid");
            String is_subscribe = (String)resultMap.get("is_subscribe");
            String trade_type = (String)resultMap.get("trade_type");
            String bank_type = (String)resultMap.get("bank_type");
            Integer total_fee = Integer.parseInt((String)resultMap.get("total_fee"));
            String fee_type = (String)resultMap.get("fee_type");
            Integer cash_fee = Integer.parseInt((String)resultMap.get("cash_fee"));
            if(resultMap.containsKey("coupon_fee")){
                Integer coupon_fee_total = Integer.parseInt((String)resultMap.get("coupon_fee"));
                if(coupon_fee_total != null && coupon_fee_total.intValue() > 0){
                    parameters.put("coupon_fee",coupon_fee_total);
                    Integer coupon_count = Integer.parseInt((String)resultMap.get("coupon_count"));
                    if(coupon_count != null && coupon_count.intValue() > 0){
                        parameters.put("coupon_count",coupon_count);
                        for(int i=0;i<coupon_count;i++){
                            String coupon_id = (String)resultMap.get("coupon_id_"+i);
                            Integer coupon_fee = Integer.parseInt((String)resultMap.get("coupon_fee_"+i));
                            parameters.put("coupon_id_"+i,coupon_id);
                            parameters.put("coupon_fee_"+i,coupon_fee);
                        }
                    }
                }
            }
            
            String transaction_id = (String)resultMap.get("transaction_id");
            String out_trade_no = (String)resultMap.get("out_trade_no");
            
            String time_end = (String)resultMap.get("time_end");
            if("SUCCESS".equalsIgnoreCase(return_code)){
                
                parameters.put("return_code", return_code);  
                if(StringUtils.isNotEmpty(return_msg)){
                    parameters.put("return_msg", return_msg);  
                }
                parameters.put("appid",appid);
                parameters.put("mch_id",mch_id);
                if(StringUtils.isNotEmpty(device_info)){
                    parameters.put("device_info", device_info);  
                }
                parameters.put("nonce_str",nonce_str);
                parameters.put("result_code",result_code);
                if(StringUtils.isNotEmpty(err_code)){
                    parameters.put("err_code", err_code);  
                }
                if(StringUtils.isNotEmpty(err_code_des)){
                    parameters.put("err_code_des", err_code_des);  
                }
                parameters.put("openid",openid);
                if(StringUtils.isNotEmpty(is_subscribe)){
                    parameters.put("is_subscribe", is_subscribe);  
                }
                parameters.put("trade_type",trade_type);
                parameters.put("bank_type",bank_type);
                parameters.put("total_fee",total_fee);
                if(StringUtils.isNotEmpty(fee_type)){
                    parameters.put("fee_type", fee_type);  
                }
                parameters.put("cash_fee",cash_fee);
                
                if(resultMap.containsKey("cash_fee_type")){
                    String cash_fee_type = (String)resultMap.get("cash_fee_type");
                    parameters.put("cash_fee_type", cash_fee_type);  
                }
                parameters.put("transaction_id",transaction_id);
                parameters.put("out_trade_no",out_trade_no);
                if(resultMap.containsKey("attach")){
                    String attach = (String)resultMap.get("attach");
                    parameters.put("attach", attach);  
                }
                parameters.put("time_end",time_end);
                //从redis取商户密钥
                String key = redisTemplate.boundValueOps(mch_id).get();
                
                String signParam = SignUtils.createSign("UTF-8", parameters, key);//参数签名
                if(sign.equals(signParam)){
                    //签名通过，处理业务逻辑
                    iWxPayTransactionService.handlePayNotify(parameters);
                    
                }else{
                    //签名不通过，response微信
                    StringBuffer sb = new StringBuffer();
                    sb.append("<xml>");
                    sb.append("<return_code><![CDATA[SUCCESS]]></return_code>");
                    sb.append("<return_msg><![CDATA[签名失败]]></return_msg>");
                    sb.append("</xml>");
                    return sb.toString();
                }
            }else{
                logger.info("微信支付异步通知return_code=="+return_code);
                StringBuffer sb = new StringBuffer();
                sb.append("<xml>");
                sb.append("<return_code><![CDATA[SUCCESS]]></return_code>");
                sb.append("<return_msg><![CDATA[return_code为FAIL]]></return_msg>");
                sb.append("</xml>");
                return sb.toString();
            }
        }catch (Exception e) {
            logger.error("处理微信支付通知异常！",e);
        }
        
        //处理成功
        StringBuffer sb = new StringBuffer();
        sb.append("<xml>");
        sb.append("<return_code><![CDATA[SUCCESS]]></return_code>");
        sb.append("<return_msg><![CDATA[OK]]></return_msg>");
        sb.append("</xml>");
        return sb.toString();
    }
    
}
